package cc.comac.mom.redis;

import java.io.Serializable;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;

import javax.annotation.Resource;

import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.support.atomic.RedisAtomicLong;
import org.springframework.stereotype.Component;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

@Component
public class IdFactory {

	@Resource
	private RedisTemplate<String, Serializable> redisTemplate;
	
	@Resource
	private JedisPool jedisPool; 

	/**
	 * 获取有过期时间的自增长ID
	 * 初始值为0
	 * @param key
	 * @param expireTime 
	 * @return
	 */
	public long generate(String key, Date expireTime) {
		
		
		Jedis jedis = jedisPool.getResource();
		Long incr = jedis.incr(key);
		jedis.expire(key, 20);
		

		
		
		RedisAtomicLong counter = new RedisAtomicLong(key, redisTemplate.getConnectionFactory());
		Long expire = counter.getExpire();
		if (expire == -1) {
			counter.expireAt(expireTime);
		}
//		return counter.incrementAndGet();
		return counter.getAndIncrement();
	}
	
	/**
	 * 获取有过期时间的自增长ID
	 * 初始值为0
	 * @param key
	 * @param expireTime 
	 * @return
	 */
	public long generate(String key, int expireTime) {
		
		
		Jedis jedis = jedisPool.getResource();
		if(expireTime>0) {
			jedis.expire(key, expireTime);
		}
		return jedis.incr(key);
	}

	
	/**
	 * 
	 * @param now
	 * now 来生成格式
	 * @return
	 * yyyy年4位MM月2位dd日2位时分秒6位
	 */
	public static String getOrderIdPrefix(LocalDateTime now) {
		return now.format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss"));
	}
	/**
	 * 
	 * @param now
	 * now 来生成格式
	 * @return
	 * yyyy年4位MM月2位dd日2位时分秒6位
	 */
	public static String getDateFormat(LocalDateTime now) {
		return now.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
	}
	
	/**
	 * 
	 * @param now
	 * now 时间 来生成格式
	 * @return
	 * yyy年3位ww周2位，星期1位
	 */
	public static String  getYearWeek(LocalDateTime now) {
		String format = now.format(DateTimeFormatter.ISO_WEEK_DATE);
		return format.replaceAll("W", "").replaceAll("-", "").substring(1);
	}
	
	/**
	 * 
	 * @param now
	 * now 时间 来生成格式
	 * @return
	 * yyy年3位ww周2位，星期1位（1-7）时分秒6位
	 */
	public static String  getYearWeekTime(LocalDateTime now) {
		String format = now.format(DateTimeFormatter.ISO_WEEK_DATE);
		String format2 = now.format(DateTimeFormatter.ofPattern("HHmmss"));
		return format.replaceAll("W", "").replaceAll("-", "").substring(1)+format2;
	}
	/**
	 * 获取过期时间
	 * @param now
	 * now 加20秒为过期时间
	 * @return
	 */
	public Date getExpireAtTime(LocalDateTime now) {
		ZoneId zoneId = ZoneId.systemDefault();
		LocalDateTime localDateTime = now.plusSeconds(20);
		ZonedDateTime zdt = localDateTime.atZone(zoneId);
		Date date = Date.from(zdt.toInstant());
		return date;
	}
	
	/**
	 * 获取过期时间
	 * @param now
	 *
	 * @return
	 */
	public Date getExpireAtTime(LocalDateTime now,int seconds) {
		ZoneId zoneId = ZoneId.systemDefault();
		LocalDateTime localDateTime = now.plusSeconds(seconds);
		ZonedDateTime zdt = localDateTime.atZone(zoneId);
		Date date = Date.from(zdt.toInstant());
		return date;
	}
	/**
	 * 生成id为当前日期（yyMMddHHmmss）+6位（从000000开始不足位数补0）工20位
	 * @return
	 */
	public String generateOrderId() {
		LocalDateTime now = LocalDateTime.now();
		String orderIdPrefix = getOrderIdPrefix(now);// 生成yyyyMMddHHmmss
		String orderId = orderIdPrefix + String.format("%1$06d", generate(orderIdPrefix, getExpireAtTime(now)));
		return orderId;

	}
	/**
	 * 生成id为当前日期（yyy年3位ww周2位，星期1位（1-7）时分秒6位）+7位（从0000000开始不足位数补0）工19位，为long最大位数
	 * 最大支持1秒生成1千万个ID，即一秒最大并发1千万，超过次并发数量需要重新设计ID生成策略
	 * @return
	 */
	public long generateId() throws RuntimeException{
		LocalDateTime now = LocalDateTime.now();
		String orderIdPrefix = getYearWeekTime(now);// 生成yyywww
		//long类型最大值9223372036854775807，如果前12位打于922300000000L系统报异常
		//922300 表示 X922年 30周 0不会出现，1到7表示礼拜1到礼拜天
		if(Long.valueOf(orderIdPrefix) > 922300000000L) {
			throw new RuntimeException("current date is bigger X922 year 30 week!");
		}
		//%后的1指第一个参数，当前只有一个可变参数，所以就是指此参数。
		//$后的0表示，位数不够用0补齐，如果没有这个0（如%1$nd）就以空格补齐，0后面的n表示总长度，总长度可以可以是大于9例如（%1$010d），d表示将按十进制转字符串，长度不够的话用0或空格补齐。
		
//		String orderId = orderIdPrefix + String.format("%1$07d", generate(orderIdPrefix, getExpireAtTime(now)));
		String orderId = orderIdPrefix + String.format("%1$07d", generate(orderIdPrefix, 20));
		return Long.valueOf(orderId);

	}
	/**
	 * 生成id为当前日期（yyMMddHHmmss）+6位（从000000开始不足位数补0）工20位
	 * @return
	 */
	public String generateBaseNo() {
		LocalDateTime now = LocalDateTime.now();
		String orderIdPrefix = getDateFormat(now);// 生成yyyyMMddHHmmss
		String orderId = orderIdPrefix + String.format("%1$03d", generate(orderIdPrefix, getExpireAtTime(now,24*60*60)));
		return orderId;

	}
	
}
